AWS SDK for JavaScript v3でDynamoDB JSONと通常のJSONの間でデータ構造の変換を行う ~ lib-dynamodb ~
いわさです。
先日、AWS SDK for JavaScriptでDynamoDBClientで項目をスキャンした際に、DynamoDBによるデータ型記述子を、util-dynamodb
を使ってアンマーシャリングする方法を紹介しました。
前回は、util-dynamodb
を使って明示的に変換を行っていました。
他の方法として、lib-dynamodb
を使うと透過的に通常のJSON形式でオブジェクトを取得することが出来ます。(内部はutil-dynamodb
を使用しています)
client-dynamodb
おさらいですが、通常のDynamoDBClientを使ったスキャン処理は以下のような形になります。
const { DynamoDBClient, ScanCommand } = require("@aws-sdk/client-dynamodb"); const client = new DynamoDBClient({ region: "ap-northeast-1" }); const command = new ScanCommand({ TableName: "hoge" }); const run = async() => { const response = await client.send(command); response.Items.forEach(function(item){ console.log(item) }) } run();
$ node hoge.js { id: { S: '2' }, num1: { N: '111' }, str1: { S: 'hoge2' } } { id: { S: '1' }, num1: { N: '222' }, str1: { S: 'hoge1' } }
DynamoDBのデータ型記述子が追加されていますね。
lib-dynamodbのコマンドを使う
lib-dynamodb
ではDynamoDBDocumentClientなど、データ型記述子などのDynamoDBの仕様を抽象化して通常のJSONのように扱うためのライブラリです。
主に、前回の記事でご紹介したマーシャリング/アンマーシャリングの部分を担うコマンド群や、変換時のオプションを設定するためのDynamoDBDocumentClient
が含まれています。
本日はこれらを導入して使ってみたいと思います。
$ npm install @aws-sdk/lib-dynamodb npm WARN 0509dynamo@1.0.0 No description npm WARN 0509dynamo@1.0.0 No repository field. + @aws-sdk/lib-dynamodb@3.87.0 added 2 packages from 1 contributor and audited 76 packages in 4.638s 2 packages are looking for funding run `npm fund` for details found 0 vulnerabilities ╭────────────────────────────────────────────────────────────────╮ │ │ │ New major version of npm available! 6.14.10 → 8.10.0 │ │ Changelog: https://github.com/npm/cli/releases/tag/v8.10.0 │ │ Run npm install -g npm to update! │ │ │ ╰────────────────────────────────────────────────────────────────╯
まずは、スキャンコマンドをclient-dynamodb
からlib-dynamodb
のものに変換してみます。
いくつかのコマンドはそのまま使えるのですが、パラメータや名称の互換がないコマンドもあったので、個別のリファレンスを確認のうえご利用ください。
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb"); const { ScanCommand } = require("@aws-sdk/lib-dynamodb"); const client = new DynamoDBClient({ region: "ap-northeast-1" }); const command = new ScanCommand({ TableName: "hoge" }); const run = async() => { const response = await client.send(command); response.Items.forEach(function(item){ console.log(item) }) } run();
$ node hoge.js { id: '2', num1: 111, str1: 'hoge2' } { id: '1', num1: 222, str1: 'hoge1' }
後述するDynamoDBDocumentClient
を使うとプレーンなJSONで利用出来るという記述をWeb上でいくつか見かけましたが、私が検証した限りではコマンドをlib-dynamodb
のものを利用することが必要でした。
DynamoDBDocumentClientで変換オプションを指定出来る
次に、DynamoDBDocumentClient
を使ってみます。
こちらのクライアントを使ったうえで先程のコマンドを実行するとマーシャリング/アンマーシャリング時の変換オプションを制御することが出来ます。
ここではアンマーシャリング時に数値フィールドをJavaScriptの数値ではなくて文字列として変換するように指定します。
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb"); const { unmarshall, marshall } = require("@aws-sdk/util-dynamodb"); const { DynamoDBDocumentClient, ScanCommand } = require("@aws-sdk/lib-dynamodb"); const client = new DynamoDBClient({ region: "ap-northeast-1" }); const command = new ScanCommand({ TableName: "hoge" }); const marshallOptions = { }; const unmarshallOptions = { wrapNumbers: false, }; const translateConfig = { marshallOptions, unmarshallOptions }; const run = async() => { const response = await DynamoDBDocumentClient.from(client, translateConfig).send(command); console.log(response.DynamoDBDocumentClientResolvedConfig) response.Items.forEach(function(item){ console.log(item) }) } run();
# wrapNumbers: true $ node hoge.js { id: '2', num1: { value: '111' }, str1: 'hoge2' } { id: '1', num1: { value: '222' }, str1: 'hoge1' } # wrapNumbers: false $ node hoge.js { id: '2', num1: 111, str1: 'hoge2' } { id: '1', num1: 222, str1: 'hoge1' }
デフォルトではJavaScript上も数値として変換されますが、キャストする際に問題が出る際に安全にフィールドを利用することが出来ます。
さいごに
本日は、先日の記事を補足する形で、lib-dynamodb
を使ったDynamoDBオブジェクトのマーシャリング/アンマーシャリングについて紹介しました。
util-dynamodb
を明示的に利用する際はアイテム毎に個別に処理してやる必要がありましたが、今回はコマンドレベルで適用すれば済むので変換を意識せずに抽象化して利用することが出来ます。
DynamoDBの低レイヤーのオブジェクト情報が必要なければ、lib-dynamodb
を利用することが推奨されています。